package com.bjsxt.commu3;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 商品工厂类
 */
public class ProductFactory {

    //存储商品（增加、删除操作多，使用LinkedList效率更高）
    List<String> productList = new LinkedList<>();
    int max = 10;

    Lock lock = new ReentrantLock();
    //两个等待队列
    Condition productCondition = lock.newCondition();
    Condition consumeCondition = lock.newCondition();

    public ProductFactory() {
    }

    public ProductFactory(int max) {
        this.max = max;
    }

    //生产一件商品
    public void produce(String name) {

        lock.lock();

        try {
            //若库存已满，则生产者等待
            //若使用if，会导致生产者被唤醒后直接执行下面的代码，导致生产过多
            while (productList.size() == max) {
                try {
                    //System.out.println("库存已满，生产者等待中...");
                    //this.wait();
                    productCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            productList.add(name);
            System.out.println(Thread.currentThread().getName() + "生产了：" + name + "，当前库存：" + productList.size());

            //库存是否已满，都可以精准通知一个消费者消费
            consumeCondition.signal();

        } finally {
            lock.unlock();
            //synchronized会自动
        }

    }

    //消费一件商品
    public void consume() {

        lock.lock();

        try {
            //若库存为空，则消费者等待
            //若使用if，会导致消费者被唤醒后直接执行下面的代码，导致消费过多
            while (productList.size() == 0) {
                try {
                    //System.out.println("库存为空，消费者等待中...");
                    //this.wait();
                    consumeCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            String name = productList.remove(0);
            System.out.println(Thread.currentThread().getName() + "消费了：" + name + "，当前库存：" + productList.size());

            //若有消费，则通知生产者生产
            productCondition.signalAll();       //可以唤醒所有生产者生产

        } finally {
            lock.unlock();
        }
    }

}
